/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package DSENS;

import java.util.ArrayList;

/**
 *
 * @author teeteto
 */
public class GridNode extends Node{

    public enum NodeType{RB, CE, WN};

    public NodeType type;

    public double ips; //instructions per second
    public double aqwt; //average queue waiting time
    public double lb; //load balancing
    public double bandwidth; //bandwidth of network

    public Log l;
    private ArrayList<Event> eventQueue;
    private int eventIndex;

    //scheduling dependent parameters
    public double ph_vector[];
    public double ph_evap;

    public double getAqwt() {
        return aqwt;
    }

    public void setAqwt(double aqwt) {
        this.aqwt = aqwt;
    }

    public double getIps() {
        return ips;
    }

    public void setIps(double ips) {
        this.ips = ips;
    }

    public double getLb() {
        return lb;
    }

    public void setLb(double lb) {
        this.lb = lb;
    }

    public double getPh_evap() {
        return ph_evap;
    }

    public void setPh_evap(double ph_evap) {
        this.ph_evap = ph_evap;
    }

    public double[] getPh_vector() {
        return ph_vector;
    }

    public void setPh_vector(double[] ph_vector) {
        this.ph_vector = ph_vector;
    }

    public NodeType getType() {
        return type;
    }

    public void setType(NodeType type) {
        this.type = type;
    }

    public double getBandwidth() {
        return bandwidth;
    }

    public void setBandwidth(double bandwidth) {
        this.bandwidth = bandwidth;
    }

    public GridNode(NodeType type) {
        this.type = type;
        this.l = new Log();
        this.eventIndex=0;
        this.eventQueue=new ArrayList<Event>(1);
    }

    public GridNode(NodeType type, double ips) {
        this.type = type;
        this.ips = ips;
        this.l = new Log();
        this.eventIndex=0;
        this.eventQueue=new ArrayList<Event>(1);
    }

    public GridNode(NodeType type, double ips, double bandwidth) {
        this.type = type;
        this.ips = ips;
        this.bandwidth = bandwidth;
        this.l = new Log();
        this.eventIndex=0;
        this.eventQueue=new ArrayList<Event>(1);
    }

    @Override
    public void receiveEvent(Event e) {
        NodeState ns;
        NodeType nt;
        try {
            if(this.getState().equals(NodeState.ON)){
                l.printEvent(e, "receiving job");
            }
            else if(this.getState().equals(NodeState.WORKING)){
                if(e.geteventType().equals("ENDjob")) return;
                else{
                    l.printEvent(e, "receiving event");
                    this.eventQueue.add(e);
                    l.printEvent(e, "job added in queue");
                    }
                }
            }catch (Exception ex) {ex.printStackTrace();}
    }

    @Override
    public void manageEvent(Event e) {
        int ttl;
        NodeState ns;
        try{
            if(this.type==NodeType.WN){
                if(this.getState().equals(NodeState.ON)){
                    this.setState(NodeState.WORKING);
                    l.printEvent(e, "Begin execution of JOB "+e.getID());
                    e.seteventType("ENDjob");
                    GlobalInfo.TIMELINE.addEvent(e.getMessage().getTimetolive(), e);
                }else if(this.getState().equals(NodeState.WORKING)){
                    if(e.geteventType().equals("ENDjob")){
                    l.printlnLog("Endind execution of JOB "+e.getID());
                    l.printlnLog("checking for other events");
                    if(this.eventIndex<this.eventQueue.size()){
                        e = this.eventQueue.get(this.eventIndex);
                        this.eventIndex++;
                        l.printEvent(e, "getting job from node queue");
                        l.printEvent(e, "Begin execution of event "+e.getID());
                        e.seteventType("internal");
                        GlobalInfo.TIMELINE.addEvent(e.getMessage().getTimetolive(), e);
                    }else{
                        l.printlnLog("No events found");
                        this.setState(NodeState.ON);
                    }
                 }
             }
            }
            else if(this.type==NodeType.CE){
                l.printEvent(e, "CE ("+this.ID+") has receved a job:");
                int index=0;
                //random
                index= (int)(Math.random()*this.neighborood.size());
                //setting up the WN that will receive the job
                e.setrcvNodeID(this.neighborood.get(index).getId());
                e.setDistance(1);
                //send job
                GlobalInfo.TIMELINE.addEvent(e.getDistance(), e);
                l.printEvent(e, "Job submitted to WN ("+this.neighborood.get(index).getId()+")");
            }
            else if(this.type==NodeType.RB){
                l.printEvent(e, "RB ("+this.ID+") has receved a job");
                int index=0;
                //random
                index= (int)(Math.random()*10)+3;
                //setting up the CE that will receive the job
                e.setrcvNodeID(index);
                e.setDistance(1);
                //send job
                GlobalInfo.TIMELINE.addEvent(e.getDistance(), e);
                l.printEvent(e, "Job submitted to CE ("+index+")");
            }
          }catch (Exception ex) {ex.printStackTrace();}
    }




}
